package com.neo.tiny.middle.socket.tomp.listener;

import cn.hutool.json.JSONUtil;
import com.neo.tiny.middle.socket.tomp.principal.StompPrincipal;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.messaging.SessionConnectedEvent;
import org.springframework.web.socket.messaging.SessionDisconnectEvent;
import org.springframework.web.socket.messaging.SessionSubscribeEvent;
import org.springframework.web.socket.messaging.SessionUnsubscribeEvent;

import static java.util.Objects.requireNonNull;

/**
 * @Description: WebSocket客户端状态监听
 * @Author: yqz
 * @CreateDate: 2023/1/14 11:49
 */
@Slf4j
@Component
public class WebSocketEventListener {

    /**
     * 监听客户端连接
     * SessionConnectedEvent（对应WebSocket 的 @OnOpen 注解）
     *
     * @param event 连接事件对象
     */
    @EventListener
    public void handleWebSocketConnectListener(SessionConnectedEvent event) {
        StompPrincipal principal = JSONUtil.toBean(JSONUtil.toJsonStr(event.getUser()), StompPrincipal.class);
        log.info("WebSocket 客户端已连接: {}",
                "{ 客户端主机名: " + principal.getName() +
                        ", 客户端主机IP地址: " + principal.getPublicName() +
                        ", 会话ID: " + requireNonNull(event.getMessage().getHeaders().get("simpSessionId")) + " }");
    }

    /**
     * 监听客户端关闭事件
     * SessionDisconnectEvent （对应WebSocket 的 @OnClose 注解）
     *
     * @param event 关闭事件对象
     */
    @EventListener
    public void handleWebSocketCloseListener(SessionDisconnectEvent event) {
        StompPrincipal principal = JSONUtil.toBean(JSONUtil.toJsonStr(event.getUser()), StompPrincipal.class);
        log.info("WebSocket 客户端已关闭: {}",
                "{ 客户端主机名: " + principal.getName() +
                        ", 客户端主机IP地址: " + principal.getPublicName() +
                        ", 会话ID: " + requireNonNull(event.getMessage().getHeaders().get("simpSessionId")) + " }");
    }

    /**
     * 监听客户端订阅事件
     * SessionSubscribeEvent （订阅事件会话）
     *
     * @param event 订阅事件对象
     */
    @EventListener
    public void handleSubscription(SessionSubscribeEvent event) {
        StompPrincipal principal = JSONUtil.toBean(JSONUtil.toJsonStr(event.getUser()), StompPrincipal.class);
        log.info("WebSocket 客户端已订阅: {}",
                "{ 客户端主机名: " + principal.getName() +
                        ", 客户端主机IP地址: " + principal.getPublicName() +
                        ", 订阅节点: " + requireNonNull(event.getMessage().getHeaders().get("simpDestination")) + " }");
    }

    /**
     * 监听客户端取消订阅事件
     * SessionUnsubscribeEvent （取消订阅事件会话）
     *
     * @param event 取消订阅事件对象
     */
    @EventListener
    public void handleUnSubscription(SessionUnsubscribeEvent event) {
        StompPrincipal principal = JSONUtil.toBean(JSONUtil.toJsonStr(event.getUser()), StompPrincipal.class);
        log.info("WebSocket 客户端已取消订阅: {}",
                "{ 客户端主机名: " + principal.getName() +
                        ", 客户端主机IP地址: " + principal.getPublicName() +
                        ", 取消订阅节点: " + requireNonNull(event.getMessage().getHeaders().get("simpDestination")) + " }");
    }
}
